/**
 * 1.收集css规则
 * 2.计算选择器与元素是否匹配
 * 3.
 */

const css = require('css')
let rules = []
let cssCompute= {}

cssCompute.addCssRules = function(text){
  let ast = css.parse(text);
  console.log(ast)
  rules.push(...ast.stylesheet.rules)
}

//判断当前选择器与元素是否匹配
function match(element, selector){
  if(!selector || !element.attributes){
    return false;
  }
  if(selector.charAt(0) == "#"){
    // id选择器
    let attr = element.attributes.filter(attr => attr.name == "id")[0]
    if(attr && attr.value == selector.replace("#","")){
      return true;
    }
      
  } else if(selector.charAt(0) == "."){
    // class选择器
    let attr = element.attributes.filter(attr => attr.name == "class")[0]
    if(attr && attr.value == selector.replace(".","")){
      return true;
    }
  } else if(element.tagName == selector){
    return true;
  }
  return false;
}

//计算specificity
function specificity(selector){
  let p = [0, 0, 0, 0]
  let selectorParts = selector.split(" ")
  for (let part of selectorParts){
    if(part.charAt(0) == "#"){
      p[1] += 1;
    } else if(part.charAt(0) == "."){
      p[2] += 1;
    } else{
      p[3] += 1;
    }
  }
  return p
}

function compare(sp1, sp2){
  let specificityLength = 4;
  for(let i=0; i < specificityLength; i++){
    if(sp1[i] - sp2[i]){
      return sp1[i]-sp2[i]
    }
  }
}

cssCompute.computeCSS = function (element,stack){
  
  //从子到父节点排序
  let elements = stack.slice().reverse();
  if(!element.computedStyle){
    element.computedStyle = {}
  }

  for(let rule of rules){
    //复合选择器解析
    let selectorParts = rule.selectors[0].split(" ").reverse();

    //当前选择器与当前元素匹配
    if(!match(element, selectorParts[0])){
      continue;
    }

    let matched = false; //是否匹配标记
    let j=1;//当前选择器位置
    for(let i=0; i < elements.length; i++){
      if(match(elements[i], selectorParts[j])){
        j++;
      }
    }

    if(j >= selectorParts.length){
      matched = true;
    }

    //匹配成功后加入相应的computedStyle到相应dom
    if(matched){
      // console.log('匹配成功,要将dom树添加对应的css拉')
      //计算specificity优先级
      let sp = specificity(rule.selectors[0])
      let computedStyle = element.computedStyle;

      for(let declaration of rule.declarations){
        if(!computedStyle[declaration.property]){
          computedStyle[declaration.property] = {}
        }

        //设置specificity
        if(!computedStyle[declaration.property].specificity) {
          computedStyle[declaration.property].specificity = sp;
        } else if(compare(computedStyle[declaration.property].specificity, sp) < 0){
          computedStyle[declaration.property].specificity = sp;
        }

        computedStyle[declaration.property].value = declaration.value
      }
      console.log(element.computedStyle)
    }
  }

}

module.exports = cssCompute